<?php

namespace app\common\model;


use app\common\BaseModel;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use think\Model;

class AdminUser extends BaseModel
{
    public static $fieldTypes = [
        'id' => 'number',
        'username' => 'string',
        'status' => 'number',
        'login_ip' => 'string',
        'created_at' => 'date',
        'login_time' => 'date',
    ];

    /**
     * 管理员登录
     * @param $data
     * @return AdminUser|array|mixed|Model
     * @throws DataNotFoundException
     * @throws DbException
     * @throws Exception
     * @throws ModelNotFoundException
     */
    public static function login($data)
    {
        $curTime = time();
        $datetime = date('Y-m-d H:i:s');
        $username = $data['username'];
        $password = $data['password'];
        $max_fail_num = config('set.login_limited.pwd_fail_num');
        $every_second = config('set.login_limited.every_second');

        if (!$manager = self::findUserName($username)) {
            throw new Exception('账号不存在');
        }

        if($manager->status != self::ENABLED_STATUS){
            throw new Exception('当前账号已被禁用，请联系管理员处理。');
        }

        $last_fail_time = !empty($manager->last_fail_time) ? strtotime($manager->last_fail_time) : 0;

        if($manager->failnum >= $max_fail_num && $curTime - $last_fail_time <= $every_second) {
            throw new Exception('超过最大失败次数，请稍后再试');
        }

        $current_password = self::encryptPassword($password, $manager->salt);

        if ($manager->encrypt_password !== $current_password) {
            //超过最大时间限制，重置失败次数
            if($curTime - $last_fail_time > $every_second) {
                $manager->failnum = 1;
            }else{
                $manager->failnum += 1;
            }

            $manager->last_fail_time = $datetime;
            $manager->save();
            throw new Exception('密码错误');
        }

        $manager->loginnum += 1;
        $manager->last_time = !empty($manager->login_time) ? $manager->login_time : $datetime;
        $manager->login_time = $datetime;
        $manager->login_ip = request()->ip();
        $manager->save();
        return $manager;
    }

    /**
     * 保存数据
     * @param $data
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws Exception
     * @throws ModelNotFoundException
     */
    public static function saveData($data)
    {
        if(empty($data['id'])) {
            if(self::findUserName($data['username'])) {
                throw new Exception('管理员账号不能重复');
            }

            //密码盐
            $salt = random_string();

            self::insertGetId([
                'username' => $data['username'],
                'salt' => $salt,
                'group_id' => 1,//管理员组，后续拓展管理员组和权限
                'encrypt_password' => self::encryptPassword($data['password'], $salt)
            ]);
        }else{
            $curUserId = request()->user['user_id'];

            if(!$modelRecord = self::findById($data['id'])) {
                throw new Exception('管理员不存在或已删除');
            }

            if($modelRecord->id == $curUserId) {
                throw new Exception('不能修改当前管理员信息');
            }

            if(!empty($data['username'])) {
                if($modelRecord->username != $data['username']) {
                    if(self::findUserName($data['username'])) {
                        throw new Exception('管理员账号不能重复');
                    }
                }

                $modelRecord->username = $data['username'];
            }

            if(!empty($data['password'])) {
                $modelRecord->salt = random_string();
                $modelRecord->encrypt_password = self::encryptPassword($data['password'], $modelRecord->salt);
            }

            if(isset($data['status'])) {
                $modelRecord->status = $data['status'];
            }

            $modelRecord->save();
        }
    }

    /**
     * 修改个人密码
     * @param $data
     * @return AdminUser|array|mixed|Model|null
     * @throws DataNotFoundException
     * @throws DbException
     * @throws Exception
     * @throws ModelNotFoundException
     */
    public static function changeProfilePassword($data)
    {
        $curUserId = request()->user['user_id'];

        $manager = self::findNoDeleted(['id' => $curUserId]);

        $originalPassword = $manager::encryptPassword($data['origin_password'], $manager->salt);
        if($originalPassword != $manager->encrypt_password) {
            throw new Exception('原密码错误');
        }

        $manager->salt = random_string();
        $manager->encrypt_password = $manager::encryptPassword($data['new_password'], $manager->salt);
        $manager->save();
        return $manager;
    }

    /**
     * 密码加密
     * @param $password
     * @param $salt
     * @return string
     */
    protected static function encryptPassword($password, $salt)
    {
        return md5($salt. $password . md5($password . md5($salt)));
    }

    /**
     * 根据账号查询管理员
     * @param $username
     * @return AdminUser|array|mixed|Model|null
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public static function findUserName($username) {
        return self::findNoDeleted(['username' => $username]);
    }

    /**
     * 删除数据
     * @param $data
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws Exception
     * @throws ModelNotFoundException
     */
    public static function delData($data) {
        $id = !empty($data['id']) ? $data['id'] : 0;

        $modelRecord = self::findNoDeleted(['id' => $id]);
        if (empty($modelRecord)) {
            throw new Exception('未知数据');
        }

        $curUserId = request()->user['user_id'];
        if($curUserId == $id) {
            throw new Exception('不能删除当前管理员');
        }

        $modelRecord->is_deleted = self::YES_DELETED;
        $modelRecord->deleted_at = date('Y-m-d H:i:s');
        $modelRecord->save();
    }
}